home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / gr564s.zip / SRC / RCSFCMP.C < prev    next >
C/C++ Source or Header  |  1992-09-05  |  8KB  |  325 lines

  1. /*
  2.  *                     RCS file comparison
  3.  */
  4. /*****************************************************************************
  5.  *                       rcsfcmp()
  6.  *                       Testprogram: define FCMPTEST
  7.  *****************************************************************************
  8.  */
  9.  
  10. /* Copyright (C) 1982, 1988, 1989 Walter Tichy
  11.    Copyright 1990, 1991, 1992 by Paul Eggert
  12.    Distributed under license by the Free Software Foundation, Inc.
  13.  
  14. This file is part of RCS.
  15.  
  16. RCS is free software; you can redistribute it and/or modify
  17. it under the terms of the GNU General Public License as published by
  18. the Free Software Foundation; either version 2, or (at your option)
  19. any later version.
  20.  
  21. RCS is distributed in the hope that it will be useful,
  22. but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24. GNU General Public License for more details.
  25.  
  26. You should have received a copy of the GNU General Public License
  27. along with RCS; see the file COPYING.  If not, write to
  28. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  
  30. Report problems and direct all questions to:
  31.  
  32.     rcs-bugs@cs.purdue.edu
  33.  
  34. */
  35.  
  36.  
  37.  
  38.  
  39.  
  40. /* $Log: rcsfcmp.c,v $
  41.  * Revision 5.10  1992/07/28  16:12:44  eggert
  42.  * Statement macro names now end in _.
  43.  *
  44.  * Revision 5.9  1991/10/07  17:32:46  eggert
  45.  * Count log lines correctly.
  46.  *
  47.  * Revision 5.8  1991/08/19  03:13:55  eggert
  48.  * Tune.
  49.  *
  50.  * Revision 5.7  1991/04/21  11:58:22  eggert
  51.  * Fix errno bug.  Add MS-DOS support.
  52.  *
  53.  * Revision 5.6  1991/02/28  19:18:47  eggert
  54.  * Open work file at most once.
  55.  *
  56.  * Revision 5.5  1990/11/27  09:26:05  eggert
  57.  * Fix comment leader bug.
  58.  *
  59.  * Revision 5.4  1990/11/01  05:03:42  eggert
  60.  * Permit arbitrary data in logs and comment leaders.
  61.  *
  62.  * Revision 5.3  1990/09/11  02:41:15  eggert
  63.  * Don't ignore differences inside keyword strings if -ko is set.
  64.  *
  65.  * Revision 5.1  1990/08/29  07:13:58  eggert
  66.  * Clean old log messages too.
  67.  *
  68.  * Revision 5.0  1990/08/22  08:12:49  eggert
  69.  * Don't append "checked in with -k by " log to logs,
  70.  * so that checking in a program with -k doesn't change it.
  71.  * Ansify and Posixate.  Remove lint.
  72.  *
  73.  * Revision 4.5  89/05/01  15:12:42  narten
  74.  * changed copyright header to reflect current distribution rules
  75.  * 
  76.  * Revision 4.4  88/08/09  19:12:50  eggert
  77.  * Shrink stdio code size.
  78.  * 
  79.  * Revision 4.3  87/12/18  11:40:02  narten
  80.  * lint cleanups (Guy Harris)
  81.  * 
  82.  * Revision 4.2  87/10/18  10:33:06  narten
  83.  * updting version number. Changes relative to 1.1 actually relative to 
  84.  * 4.1
  85.  * 
  86.  * Revision 1.2  87/03/27  14:22:19  jenkins
  87.  * Port to suns
  88.  * 
  89.  * Revision 4.1  83/05/10  16:24:04  wft
  90.  * Marker matching now uses trymatch(). Marker pattern is now
  91.  * checked precisely.
  92.  * 
  93.  * Revision 3.1  82/12/04  13:21:40  wft
  94.  * Initial revision.
  95.  *
  96.  */
  97.  
  98. /*
  99. #define FCMPTEST
  100. */
  101. /* Testprogram; prints out whether two files are identical,
  102.  * except for keywords
  103.  */
  104.  
  105. #include  "rcsbase.h"
  106.  
  107. libId(fcmpId, "$Id: rcsfcmp.c,v 5.10 1992/07/28 16:12:44 eggert Exp $")
  108.  
  109.     static int
  110. discardkeyval(c, f)
  111.     register int c;
  112.     register RILE *f;
  113. {
  114.     for (;;)
  115.         switch (c) {
  116.             case KDELIM:
  117.             case '\n':
  118.                 return c;
  119.             default:
  120.                 Igeteof_(f, c, return EOF;)
  121.                 break;
  122.         }
  123. }
  124.  
  125.     int
  126. rcsfcmp(xfp, xstatp, uname, delta)
  127.     register RILE *xfp;
  128.     struct stat const *xstatp;
  129.     char const *uname;
  130.     struct hshentry const *delta;
  131. /* Compare the files xfp and uname.  Return zero
  132.  * if xfp has the same contents as uname and neither has keywords,
  133.  * otherwise -1 if they are the same ignoring keyword values,
  134.  * and 1 if they differ even ignoring
  135.  * keyword values. For the LOG-keyword, rcsfcmp skips the log message
  136.  * given by the parameter delta in xfp.  Thus, rcsfcmp returns nonpositive
  137.  * if xfp contains the same as uname, with the keywords expanded.
  138.  * Implementation: character-by-character comparison until $ is found.
  139.  * If a $ is found, read in the marker keywords; if they are real keywords
  140.  * and identical, read in keyword value. If value is terminated properly,
  141.  * disregard it and optionally skip log message; otherwise, compare value.
  142.  */
  143. {
  144.     register int xc, uc;
  145.     char xkeyword[keylength+2];
  146.     int eqkeyvals;
  147.     register RILE *ufp;
  148.     register int xeof, ueof;
  149.     register char * tp;
  150.     register char const *sp;
  151.     int result;
  152.     enum markers match1;
  153.     struct stat ustat;
  154.  
  155.     if (!(ufp = Iopen(uname, FOPEN_R_WORK, &ustat))) {
  156.        efaterror(uname);
  157.     }
  158.     xeof = ueof = false;
  159.     if (Expand==OLD_EXPAND) {
  160.     if (!(result = xstatp->st_size!=ustat.st_size)) {
  161. #        if has_mmap && large_memory
  162.         result = !!memcmp(xfp->base,ufp->base,(size_t)xstatp->st_size);
  163. #        else
  164.         for (;;) {
  165.             /* get the next characters */
  166.             Igeteof_(xfp, xc, xeof=true;)
  167.             Igeteof_(ufp, uc, ueof=true;)
  168.             if (xeof | ueof)
  169.             goto eof;
  170.             if (xc != uc)
  171.             goto return1;
  172.         }
  173. #        endif
  174.     }
  175.     } else {
  176.     xc = 0;
  177.     uc = 0; /* Keep lint happy.  */
  178.     result = 0;
  179.  
  180.     for (;;) {
  181.       if (xc != KDELIM) {
  182.         /* get the next characters */
  183.         Igeteof_(xfp, xc, xeof=true;)
  184.         Igeteof_(ufp, uc, ueof=true;)
  185.         if (xeof | ueof)
  186.         goto eof;
  187.       } else {
  188.         /* try to get both keywords */
  189.         tp = xkeyword;
  190.         for (;;) {
  191.         Igeteof_(xfp, xc, xeof=true;)
  192.         Igeteof_(ufp, uc, ueof=true;)
  193.         if (xeof | ueof)
  194.             goto eof;
  195.         if (xc != uc)
  196.             break;
  197.         switch (xc) {
  198.             default:
  199.             if (xkeyword+keylength <= tp)
  200.                 break;
  201.             *tp++ = xc;
  202.             continue;
  203.             case '\n': case KDELIM: case VDELIM:
  204.             break;
  205.         }
  206.         break;
  207.         }
  208.         if (
  209.         (xc==KDELIM || xc==VDELIM)  &&  (uc==KDELIM || uc==VDELIM)  &&
  210.         (*tp = xc,  (match1 = trymatch(xkeyword)) != Nomatch)
  211.         ) {
  212. #ifdef FCMPTEST
  213.           VOID printf("found common keyword %s\n",xkeyword);
  214. #endif
  215.           result = -1;
  216.           for (;;) {
  217.           if (xc != uc) {
  218.               xc = discardkeyval(xc, xfp);
  219.               uc = discardkeyval(uc, ufp);
  220.               if ((xeof = xc==EOF)  |  (ueof = uc==EOF))
  221.               goto eof;
  222.               eqkeyvals = false;
  223.               break;
  224.           }
  225.           switch (xc) {
  226.               default:
  227.               Igeteof_(xfp, xc, xeof=true;)
  228.               Igeteof_(ufp, uc, ueof=true;)
  229.               if (xeof | ueof)
  230.                   goto eof;
  231.               continue;
  232.  
  233.               case '\n': case KDELIM:
  234.               eqkeyvals = true;
  235.               break;
  236.           }
  237.           break;
  238.           }
  239.           if (xc != uc)
  240.           goto return1;
  241.           if (xc==KDELIM) {
  242.           /* Skip closing KDELIM.  */
  243.           Igeteof_(xfp, xc, xeof=true;)
  244.           Igeteof_(ufp, uc, ueof=true;)
  245.           if (xeof | ueof)
  246.               goto eof;
  247.           /* if the keyword is LOG, also skip the log message in xfp*/
  248.           if (match1==Log) {
  249.               /* first, compute the number of line feeds in log msg */
  250.               int lncnt;
  251.               size_t ls, ccnt;
  252.               sp = delta->log.string;
  253.               ls = delta->log.size;
  254.               if (ls<sizeof(ciklog)-1 || memcmp(sp,ciklog,sizeof(ciklog)-1)) {
  255.             /* This log message was inserted.  */
  256.             lncnt = 3;
  257.             while (ls--) if (*sp++=='\n') lncnt++;
  258.             for (;;) {
  259.                 if (xc=='\n')
  260.                 if(--lncnt==0) break;
  261.                 Igeteof_(xfp, xc, goto returnresult;)
  262.             }
  263.             /* skip last comment leader */
  264.             /* Can't just skip another line here, because there may be */
  265.             /* additional characters on the line (after the Log....$)  */
  266.             for (ccnt=Comment.size; ccnt--; ) {
  267.                 Igeteof_(xfp, xc, goto returnresult;)
  268.                 if(xc=='\n') break;
  269.                 /*
  270.                  * Read to the end of the comment leader or '\n',
  271.                  * whatever comes first.  Some editors strip
  272.                  * trailing white space from a leader like " * ".
  273.                  */
  274.             }
  275.               }
  276.           }
  277.           } else {
  278.           /* both end in the same character, but not a KDELIM */
  279.           /* must compare string values.*/
  280. #ifdef FCMPTEST
  281.           VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
  282. #endif
  283.           if (!eqkeyvals)
  284.               goto return1;
  285.           }
  286.         }
  287.       }
  288.       if (xc != uc)
  289.           goto return1;
  290.     }
  291.     }
  292.  
  293.   eof:
  294.     if (xeof==ueof)
  295.     goto returnresult;
  296.   return1:
  297.     result = 1;
  298.   returnresult:
  299.     Ifclose(ufp);
  300.     return result;
  301. }
  302.  
  303.  
  304.  
  305. #ifdef FCMPTEST
  306.  
  307. char const cmdid[] = "rcsfcmp";
  308.  
  309. main(argc, argv)
  310. int  argc; char  *argv[];
  311. /* first argument: comment leader; 2nd: log message, 3rd: expanded file,
  312.  * 4th: unexpanded file
  313.  */
  314. {       struct hshentry delta;
  315.  
  316.     Comment.string = argv[1];
  317.     Comment.size = strlen(argv[1]);
  318.     delta.log.string = argv[2];
  319.     delta.log.size = strlen(argv[2]);
  320.     if (rcsfcmp(Iopen(argv[3], FOPEN_R_WORK, (struct stat*)0), argv[4], &delta))
  321.                 VOID printf("files are the same\n");
  322.         else    VOID printf("files are different\n");
  323. }
  324. #endif
  325.